#!/usr/bin/env python
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-

"""Integration of package managers into SystemUpdater"""

import os
import apt
import apt_pkg
import json
import logging
import subprocess
import traceback
import shutil
import fcntl
import dbus
import threading
from apt import Cache
from gettext import gettext as _
from SystemUpdater.Core.errors import *
from SystemUpdater.Core.enums import *
from SystemUpdater.Core.DataAcquisition import get_east_8_time
from SystemUpdater.Core.UpdateList import LocalUpgradeDataList
from SystemUpdater.Core.DistUpgradeCache import NotEnoughFreeSpaceError
from SystemUpdater.Core.utils import get_config_patch

class NowUpgradeMeta:
    """
    Represent the (potentially partial) results of an unattended-upgrades
    run
    """
    def __init__(self,
                parent,             
                upgrade_groups = [],   
                single_pkgs = [],
                version_upgrade = False,
                need_retry = False,
                ):
        self.parent = parent
        #组列表中包含的包
        self.upgrade_groups = upgrade_groups
        #推送的可升级的单包
        self.single_pkgs = single_pkgs
        self.version_upgrade = version_upgrade
        self.need_retry = need_retry
        self.upgrade_content = self.upgrade_groups + self.single_pkgs

        #获取当前升级的升级列表
    def _make_groups_list(self,upgrade_data,_upgrade_mode,partial_upgrade_list):
        groups_list = []
        pkg_list = []
        
        #部分升级
        if _upgrade_mode == self.parent.MODE_INSTALL_PARTIAL:
            for elem in partial_upgrade_list:
                #组升级方式
                if elem in upgrade_data.upgrade_groups:
                    groups_list.append(elem)
                #单包升级方式
                elif elem in upgrade_data.single_pkgs:
                    pkg_list.append(elem)
                else:
                    logging.warning("this package(%s) not in selected list",elem)
            
        #全部升级列表
        elif _upgrade_mode == self.parent.MODE_INSTALL_ALL:
            groups_list = upgrade_data.upgrade_groups
            pkg_list = upgrade_data.single_pkgs
        
        return groups_list,pkg_list

    def make_upgrade_content(self,content):
        if self.parent.action_mode != self.parent.MODE_INSTALL_SINGLE:
            self.upgrade_groups,self.single_pkgs = self._make_groups_list(self.parent.upgrade_data,self.parent.action_mode,content)
            self.upgrade_content = self.upgrade_groups + self.single_pkgs
        else:
            self.single_pkgs = content
            self.upgrade_content = self.upgrade_groups + self.single_pkgs

class UpdateEssentialItem():
    def __init__(self,parent):
        self.essential_pkgs = []
        self.remove_white = []

        self.read_path = get_config_patch() + 'kylin-update-desktop-system.json'
        self.update()

    def update(self):
        if os.path.exists(self.read_path):
            with open(self.read_path,'r') as f:
                try:
                    data = json.load(f)
                    self.essential_pkgs = data['install_list']
                except Exception as exc:
                    logging.warning(exc)
                try:
                    self.remove_white = data['remove_white_list']
                except Exception as exc:
                    pass
                    # logging.warning(exc)
    
    def check_essential(self,remove_pkgs):
        logging.info("Check: For remove of Essential Packages...")
        for pkg in remove_pkgs:
            if pkg in self.essential_pkgs:
                logging.error("Essential Packages(%s) will be Removed...",pkg)
                raise UpdateBaseError(ERROR_REMOVE_ESSENTIAL_PACKAGES)
    
    def check_white(self,remove_pkgs):
        logging.info("Check: remove pkg in White Packages...")
        new_upgrade_list = list(set(remove_pkgs) & set(self.remove_white))

        for pkg in new_upgrade_list:
            if pkg in remove_pkgs:
                logging.info("%s will be remove in remove pkg...",pkg)
                remove_pkgs.remove(pkg)


class AptdBaseInformation:
    """
        进度 状态 状态细节信息
    """
    def __init__(self,
                progress = 0,
                status='',
                details='',
                cancelable = False,
                error_details = '',
                ):

        self.progress = progress
        self.status = status
        self.details = details
        self.cancelable = cancelable
        self.error_details = error_details

class InstallBackend():
    INSTALL_OUTPUT_JSON = "/var/lib/kylin-system-updater/json/showdown_install.json"

    ACTION_DEFUALT_STATUS = -1
    ACTION_UPDATE = 0
    ACTION_INSTALL = 1
    ACTION_INSTALL_DEB = 2
    ACTION_CHECK_RESOLVER = 3
    ACTION_DOWNLOADONLY = 4
    ACTION_FIX_BROKEN = 5
    ACTION_REMOVE_PACKAGES = 6
    ACTION_FIX_INCOMPLETE = 7
    ACTION_CLEAN = 8
    ACTION_INSTALL_SHUTDOWN = 9
    ACTION_BACKGROUND_UPGRADE = 10
    ACTION_CHECK_BROKEN = 11

    MODE_DEFAULT_STATUS = -1
    
    #1、ACTION_INSTALL 安装的子类
    #部分升级
    MODE_INSTALL_PARTIAL = 0
    #全部升级
    MODE_INSTALL_ALL = 1
    #系统全盘升级
    MODE_INSTALL_SYSTEM = 2
    #后端内部安装包使用 目前 更新配置包和升级本身使用
    MODE_INSTALL_SINGLE = 3

    #2、更新的子类
    MODE_UPDATE_CACHE = 0
    MODE_UPDATE_ALL = 1

    def __init__(self, window_main, action,mode = MODE_DEFAULT_STATUS):
        self.window_main = window_main
        self.cache = window_main.cache
        self.action = action
        self.action_mode = mode

        self.window_main.now_working = action

        self.aptd_base = AptdBaseInformation()

        self.inhibit_shutdown = InhibitShutdownLock()

        self.update_essential = UpdateEssentialItem(self)

        if self.action == self.ACTION_INSTALL:
            self.safe_manager = UpdateSafeManager()

        #更新的时候此对象还未生成
        if self.window_main.update_list !=  None:
            self.upgrade_data = window_main.update_list.upgrade_meta
        else:
            self.upgrade_data = LocalUpgradeDataList()

        #要拿到升级列表必须调用_make_upgrade_list
        self.now_upgrade = NowUpgradeMeta(parent=self)

    def start(self,partial_upgrade_list = []):
        try:
            #安装升级包 首先必须调用ACTION_CHECK_RESOLVER 计算依赖解决方便 标记cache 进行升级
            if self.action == self.ACTION_INSTALL or self.action == self.ACTION_DOWNLOADONLY:
                #拿到升级列表
                self.now_upgrade.make_upgrade_content(partial_upgrade_list)

                pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
                logging.info("INSTALL install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),\
                                                            len(pkgs_upgrade),len(pkgs_remove),len(pkgs_downgrade))

                #当下载数量大于200个包时  就认为属于大版本升级 开启重试机制
                if len(pkgs_install) + len(pkgs_upgrade) > 100:
                    logging.info("Open a major version upgrade and Retry mechanism on...")
                    self.now_upgrade.version_upgrade = True
                
                #检查是否存在可升级的包
                if len(pkgs_install) == 0 and len(pkgs_upgrade) == 0 and len(pkgs_remove) == 0 and len(pkgs_downgrade) == 0:
                    pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,self.now_upgrade.upgrade_groups,self.now_upgrade.single_pkgs)
                    logging.warning("There is an exception in the update package install = %r upgrade = %r",pkgs_install,pkgs_upgrade)

                # if self.action_mode == self.MODE_INSTALL_SINGLE:
                #     logging.warning("MODE_INSTALL_SINGLE install:%s , upgrade:%s remove:%s",str(pkgs_install),str(pkgs_upgrade),str(pkgs_remove))

                self.update_essential.check_essential(pkgs_remove)
                
                #检查磁盘的状态 
                self.check_free_space(self.cache)

                for ul in self.window_main.collector.upgrade_list:
                    self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul})

                if self.action == self.ACTION_INSTALL:
                    self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade)
                elif self.action == self.ACTION_DOWNLOADONLY:
                    self._update_to_config(self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove)
                    self.commit_only(self.action,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade)
            
            elif self.action == self.ACTION_INSTALL_SHUTDOWN:
                self.now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove = self._config_to_upgrade()
                logging.info("ACTION_INSTALL_SHUTDOWN install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove))

                # self._start_install_lock()
                self.commit(self.action,pkgs_install, pkgs_upgrade, pkgs_remove)

            #计算依赖解决方案
            elif self.action == self.ACTION_CHECK_RESOLVER:
                #被删除包的描述
                raw_description = []

                #判断是否配置aptdaemon的限速
                self.window_main.check_conifg_aptdeamon()
                
                if self.action_mode != self.MODE_INSTALL_SYSTEM:
                    #获取要升级的组列表
                    self.now_upgrade.make_upgrade_content(partial_upgrade_list)
                    #获取要升级和安装的包列表
                    pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,self.now_upgrade.upgrade_groups,self.now_upgrade.single_pkgs)
                    #计算解决依赖关系
                    self._make_problem_resolver(self.cache,pkgs_install,pkgs_upgrade,self.upgrade_data.adjust_pkgs)
                    pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)
                else:
                    # 使用全盘升级 全盘使用dist-upgrade
                    if self.cache.get_changes():
                        self.cache.clear()
                    self.cache._depcache.upgrade(True)
                    pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade = self._get_mark_from_cache(self.cache,self.upgrade_data.adjust_pkgs,self.action_mode)

                logging.warning("ProblemResolver of the deletion package list:%s",str(pkgs_remove))
                self.update_essential.check_white(pkgs_remove)
                logging.info("RESOLVER install:%d , upgrade:%d remove:%d pkgs_downgrade:%d",len(pkgs_install),len(pkgs_upgrade),\
                                                                            len(pkgs_remove),len(pkgs_downgrade))
                is_remove_pkgs = len(pkgs_remove) != 0

                # 数据上报
                self.window_main.collector.Generate_Msg(self.now_upgrade.upgrade_groups+self.now_upgrade.single_pkgs, self.action_mode)
                errorCode = ""
                if is_remove_pkgs:
                    errorCode = _("Need remove pkgs: ")+", ".join(pkgs_remove)
                for ul in self.window_main.collector.upgrade_list:
                    self.window_main.collector.Upgrade_Process_Msg(self.action, {"appname":ul, "status":is_remove_pkgs, "errorCode":errorCode})
                
                #补充删除包的描述信息,删除描述
                delete_desc = []
                for pkg in pkgs_remove:
                    pkg_obj = self.cache[pkg]
                    raw_description.append(getattr(pkg_obj.candidate, "summary", ''))
                    delete_desc.append('')

                if self.action_mode != self.MODE_INSTALL_SYSTEM:
                    self.window_main.dbusController.UpdateDependResloveStatus(True,is_remove_pkgs,pkgs_remove,raw_description,delete_desc,'','')
                else:
                    self.window_main.dbusController.DistupgradeDependResloveStatus(True,is_remove_pkgs,pkgs_remove,raw_description,delete_desc,'','')

                self._action_done(self.action,False,True,'','')
                
                if is_remove_pkgs:
                    threading_emulate = threading.Thread(target=self._emulate_calcul_delete,args=((pkgs_upgrade + pkgs_install),))
                    threading_emulate.start()

            #修复未满足的依赖关系 与apt-get -f install匹配
            elif self.action == self.ACTION_CHECK_BROKEN:
                try:
                    #计算依赖的解决方案
                    self.cache.fix_broken()
                except Exception as e:
                    logging.error(e)
                    raise UpdateBaseError(ERROR_RESOLVER_FAILED)

                pkgs_install,pkgs_upgrade,pkgs_remove = self._get_pkgs_from_cache(self.cache)
                logging.warning("Fix broken Packages is need to install:%a and upgrade:%a and remove:%a",pkgs_install,pkgs_upgrade,pkgs_remove)

                #当存在需要卸载包的情况时 不进行修复
                if len(pkgs_remove) == 0:
                    logging.warning("start fix system broken pkgs...")
                    self.fix_broken()
                else:
                    raw_description = []
                    delete_desc = []
                    #添加关于删除包的描述信息
                    for pkg in pkgs_remove:
                        delete_desc.append('')
                        pkg_obj = self.cache[pkg]
                        raw_description.append(getattr(pkg_obj.candidate, "summary", ''))
                    
                    self.window_main.dbusController.UpdateFixBrokenStatus(True,True,pkgs_remove,raw_description,delete_desc,'','')
                    self._action_done(self.action,False,True,'','')
                    
            elif self.action == self.ACTION_FIX_BROKEN:
                pkgs_install,pkgs_upgrade,pkgs_remove = self._get_pkgs_from_cache(self.cache)

                self.update_essential.check_essential(pkgs_remove)
                self.fix_broken()
            # 修复不完整的安装dpkg configure -a
            elif self.action == self.ACTION_FIX_INCOMPLETE:
                self.fix_incomplete()
            #卸载包
            elif self.action == self.ACTION_REMOVE_PACKAGES:
                self._start_install_lock(_("Kylin System Updater"))
                self.purge_packages(partial_upgrade_list)
            elif self.action == self.ACTION_CLEAN:
                self.clean()
            #更新cache
            elif self.action == self.ACTION_UPDATE:
                #检查依赖之前 判断是否需要重启aptdeamon 目前为了生效限速功能
                self.window_main.check_conifg_aptdeamon()
                self.update()
        except UpdateBaseError as excep:
            self._action_done(self.action,True,False,excep.header,excep.desc,excep.code)
        except UpdateProgressExit as excep:
            pass
        except Exception as e:
            logging.error(e) 
            traceback.print_exc()

    def start_alone(self,partial_upgrade_list = [],_is_install = False, caller=''):
        # 安装本地deb包的接口
        if self.action == self.ACTION_INSTALL_DEB: 
            try:
                self._start_install_lock(caller=caller)
                self.install_deb(install_path = partial_upgrade_list, install_force = _is_install)
            except Exception as e:
                logging.error(str(e))
        # 安装在线包的接口
        elif self.action == self.ACTION_BACKGROUND_UPGRADE:
            try:
                pkgs_install = [ str(pkg) for pkg in partial_upgrade_list]
                logging.info("Install deb package, open cache")
                cache = Cache()
                for pkg_name in pkgs_install:
                    if pkg_name not in cache:
                        if "=" not in pkg_name or ("=" in pkg_name and pkg_name.split("=")[0] not in cache):
                        # 没找到包或格式不正确
                            self.window_main.dbusController.UpdateInstallFinished(False, pkgs_install, "'"+pkg_name+"' is not in cache", "")
                            return
                self._start_install_lock(caller=caller)
                self.commit(self.ACTION_INSTALL,pkgs_install,[],[])
            except Exception as e:
                logging.error(str(e))
                self.window_main.dbusController.UpdateInstallFinished(False, pkgs_install, str(e), "")

    def update(self):
        """Run a update to refresh the package list"""
        raise NotImplementedError

    def clean(self):
        """Remove all downloaded files.t"""
        raise NotImplementedError

    def commit(self,model,pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_downgrade = []):
        """Commit the cache changes """
        raise NotImplementedError

    def install_deb(self,install_path,install_force):
        """install_deb the cache changes """
        raise NotImplementedError

    def fix_broken(self):
        """fix_broken_depends"""
        raise NotImplementedError

    def fix_incomplete(self):
        """fix_incomplete_install"""
        raise NotImplementedError

    def purge_packages(self,pkgs_purge):
        """purge_packages"""
        raise NotImplementedError

    def _get_pkgs_from_cache(self,cache):
        pkgs_install = []
        pkgs_upgrade = []
        pkgs_remove = []

        #计算修复破损包 方案 需要删除 新装那些包
        for pkg in cache:
            try:
                if pkg.marked_install :
                    pkgs_install.append(pkg.name)
                elif pkg.marked_upgrade:
                    pkgs_upgrade.append(pkg.name)
                elif pkg.marked_delete:
                    pkgs_remove.append(pkg.name)
            except KeyError:
                # pkg missing from fresh_cache can't be modified
                pass
        return pkgs_install,pkgs_upgrade,pkgs_remove

    #从cache中拿到标记的列表
    def _get_mark_from_cache(self,cache,_adjust_pkgs,upgrade_mode):
        pkgs_install = []
        pkgs_upgrade = []
        pkgs_remove = []
        pkgs_downgrade = []

        #全盘升级不做任何的调整
        if upgrade_mode == self.MODE_INSTALL_SYSTEM or upgrade_mode == self.MODE_INSTALL_SINGLE:
            adjust_pkgs = []
        else:
            #获取调整包列表 去掉版本号
            adjust_pkgs = [i.split("=")[0] for i in _adjust_pkgs]

        for pkg in cache:
            try:
                if pkg.marked_install:
                    pkgname = pkg.name
                    if pkg.is_auto_installed:
                        pkgname += "#auto"
                    if pkg.name in adjust_pkgs:
                        pkgs_install.append(_adjust_pkgs[adjust_pkgs.index(pkg.name)])
                    else:
                        pkgs_install.append(pkgname)
                elif pkg.marked_upgrade:
                    if pkg.name in adjust_pkgs:
                        pkgs_upgrade.append(_adjust_pkgs[adjust_pkgs.index(pkg.name)])
                    else:
                        pkgs_upgrade.append(pkg.name)
                elif pkg.marked_delete:
                    pkgs_remove.append(pkg.name)
                elif pkg.marked_downgrade:
                    pkgs_downgrade.append(pkg.name+'='+pkg.candidate.source_version)
            except KeyError:
                pass
        return pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_downgrade

    #获取当前升级的升级列表
    def _make_groups_list(self,upgrade_data,_upgrade_mode,partial_upgrade_list):
        groups_list = []
        pkg_list = []
        
        #部分升级
        if _upgrade_mode == self.MODE_INSTALL_PARTIAL:
            for elem in partial_upgrade_list:
                #组升级方式
                if elem in upgrade_data.upgrade_groups:
                    groups_list.append(elem)
                #单包升级方式
                elif elem in upgrade_data.single_pkgs:
                    pkg_list.append(elem)
                else:
                    logging.warning("this package(%s) not in selected list",elem)
            
        #全部升级列表
        elif _upgrade_mode == self.MODE_INSTALL_ALL:
            groups_list = upgrade_data.upgrade_groups
            pkg_list = upgrade_data.single_pkgs
        
        return groups_list,pkg_list

    #从本地中获取本次升级需要升级的包 部分升级和全部升级使用 全盘升级不适用
    def _make_pkgs_list(self,cache,groups_pkgs,groups_list,pkg_list):
        pkgs_install = []
        pkgs_upgrade = []
        
        try:
            #单包的升级方式
            for pkg in pkg_list:
                if cache[pkg].is_installed:
                    pkgs_upgrade.append(pkg)
                else:
                    pkgs_install.append(pkg) 

            #遍历升级组列表
            for group_name in groups_list:
                pkgs_install += groups_pkgs.get(group_name,[]).get('pkgs_install',[])
                pkgs_upgrade += groups_pkgs.get(group_name,[]).get('pkgs_upgrade',[]) 
            
            return pkgs_install,pkgs_upgrade
        except Exception as e:
            logging.error(str(e))
            return [],[]
    
    def _installed_dependencies(self, pkg_name, all_deps=None):
        """Recursively return all installed dependencies of a given package."""
        # FIXME: Should be part of python-apt, since it makes use of non-public
        #       API. Perhaps by adding a recursive argument to
        #       apt.package.Version.get_dependencies()
        if not all_deps:
            all_deps = set()
        if pkg_name not in self.cache:
            return all_deps
        cur = self.cache[pkg_name]._pkg.current_ver
        if not cur:
            return all_deps
        for sec in ("PreDepends", "Depends", "Recommends"):
            try:
                for dep in cur.depends_list[sec]:
                    dep_name = dep[0].target_pkg.name
                    if dep_name not in all_deps:
                        all_deps.add(dep_name)
                        all_deps |= self._installed_dependencies(dep_name,
                                                                 all_deps)
            except KeyError:
                pass
        return all_deps

    def _split_package_id(self,package):
        """Return the name, the version number and the release of the
        specified package."""
        if "=" in package:
            name, version = package.split("=", 1)
            release = None
        elif "/" in package:
            name, release = package.split("/", 1)
            version = None
        else:
            name = package
            version = release = None
        return name, version, release

    #将获取本次升级的包 进行计算依赖关系 解决依赖问题
    def _make_problem_resolver(self,cache,pkgs_install = [],pkgs_upgrade = [],adjust_pkgs = []):
        try:
            logging.info("ProblemResolver install:%d , upgrade:%d",len(pkgs_install),len(pkgs_upgrade))
            logging.info("Start calculating dependencies...")

            #actiongroup 可以加速计算依赖关系 计算花费的时间将大幅度缩减
            with cache.actiongroup():
                if cache.get_changes():
                    cache.clear()
                resolver = apt.cache.ProblemResolver(cache)

                for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg)
                                                    for pkg in adjust_pkgs]:
                    try:
                        pkg = cache[pkg_name]
                        pkg.candidate = pkg.versions[pkg_ver]
                    except KeyError:
                        logging.warning("The version %s of %s isn't available",pkg_ver, pkg_name)
                        continue

                for pkg in pkgs_upgrade + pkgs_install:
                    pkg_cache = cache[pkg]
                    if pkg_cache.is_upgradable == False and pkg_cache.is_installed == True:
                        logging.warning("pkg(%s) not upgrade or install and will be continue...",pkg)
                        continue

                    pkg_cache.mark_install(False, True, True)

                    if pkg_cache.is_upgradable == True:
                        auto = pkg_cache.is_auto_installed
                        pkg_cache.mark_auto(auto)

                    if pkg_cache.marked_keep == True:
                        pkg_cache.mark_install(False, False, True)
                        if pkg_cache.marked_keep == True:
                            raise

                    resolver.clear(pkg_cache)
                    resolver.protect(pkg_cache)

                resolver.resolve()
            return
        except Exception as e:
            logging.error(str(e))
            pkg_string = ''
            for pkg in pkgs_install + pkgs_upgrade:
                pkg_string = pkg_string + ' ' + str(pkg)
            logging.error('Resolver calculation Packages List: '+pkg_string+'\n')
            terminal_msg = self.window_main.simulate_mode.dependencies_broken(pkgs_install + pkgs_upgrade)
            logging.error(terminal_msg)
            raise UpdateBaseError(ERROR_RESOLVER_FAILED,
                        desc= terminal_msg)

    def _emulate_calcul_delete(self,total_pkg):
        logging.info("[DELETE_DETAILS] Start calculating delete dependencies...")
        delete_pkgs = []
        last_delete_count = 0
        cache = Cache()

        with cache.actiongroup():
            if cache.get_changes():
                cache.clear()
            for pkg in total_pkg:
                if '#' in pkg:
                    pkg = pkg.split("#")[0]
                elif '=' in pkg:
                    pkg = pkg.split("=")[0]

                try:
                    cache[pkg].mark_install()
                except Exception as e:
                    logging.error(str(e))
                    break

                if cache.delete_count != last_delete_count:
                    last_delete_count = cache.delete_count
                    for pkg_obj in cache.get_changes():
                        if pkg_obj.marked_delete and pkg_obj.name not in delete_pkgs:
                            delete_pkgs.append(pkg_obj.name)
                            delete_pkgs.append(pkg)
                            logging.info("[DELETE_DETAILS] %s Will be deleted Due to Install or Upgrade %s",pkg_obj.name,pkg)
        
        logging.info("[DELETE_DETAILS] End calculating delete dependencies...")
        cache.close()

    def _send_error_code(self,error_code):
        if error_code == ERROR_NOT_DISK_SPACE:
            self.window_main.dbusController.InstallDetectStatus(False,error_code)

    def _self_upgrade_finished(self,success,error_string='',error_desc=''):
        if success:
            if self.window_main.configs_cover.getWithDefault("SystemStatusCover", "priority_upgrade_restart", False,True) == True:
                error_string = get_error_string_from_enum(PRIORITY_UPGRADE_SUCCCESSED)
                if self.window_main.APTD_PKG_NAME in self.now_upgrade.upgrade_content:
                    self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'')
                    self.window_main.dbusController.make_aptdeamon_restart()
                
                #当单包升级的时候 升级本身时，让程序退出，再重新启动
                if self.window_main.FRONTEND_PKG_NAME in self.now_upgrade.upgrade_content:
                    self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'')
                
                #当单包升级的时候 升级本身时，让程序退出，再重新启动
                if self.window_main.BACKEND_PKG_NAME in self.now_upgrade.upgrade_content:
                    self.window_main.dbusController.UpdateDetectFinished(False,[self.window_main.BACKEND_PKG_NAME],error_string,'')
                    #升级本身完成后 退出 有systemd 来进行重启服务
                    self.window_main.dbusController.Quit(None)
                    return 

                #当单包升级的时候 升级本身时，让程序退出，再重新启动
                if self.window_main.GROUPS_PKG_NAME in self.now_upgrade.upgrade_content:
                    self.window_main.start_available()
            else:
                self.window_main.start_available()
        else:
            self.window_main.dbusController.UpdateDetectFinished(False,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\
                                                                    error_string +' '+error_desc)

    #调用aptdeamon结束之后处理的地方 不管是出错还是正常都在此处理
    def _action_done(self, action, is_cancelled,success, error_string='',error_desc='',error_code=''):
        #后端的状态 到空闲状态      
        self.window_main.now_working = self.ACTION_DEFUALT_STATUS
        
        #升级完成后走的分支
        if action == self.ACTION_INSTALL:
            false_num = 0
            self.safe_manager.reset_safe()
            self._release_install_lock()
            self._send_error_code(error_code)
            
            if self.action_mode == self.MODE_INSTALL_SINGLE:
                self._self_upgrade_finished(success,error_string,error_desc)
            else:      
                if self.now_upgrade.version_upgrade == True and self.now_upgrade.need_retry == True and success == False:
                    #增加重试次数的限制
                    if self.window_main.retry_limit != 0:
                        logging.warning("Retry the upgrade and installaton(%s) and retry number: %d",self.now_upgrade.upgrade_content,self.window_main.retry_limit)
                        self.window_main.start_install(self.action_mode,True,self.now_upgrade.upgrade_content)
                        self.window_main.retry_limit = self.window_main.retry_limit - 1
                        return
                try:
                    false_num = self._make_insert_info(success,is_cancelled,self.now_upgrade,error_string,error_desc)
                except Exception as e:
                    logging.error(e)
                
                if success == False:
                    logging.info("The number of failed installations or upgrades is %d",false_num)
                
                #修复bug 所有的包都安装成功了，但是却返回的失败，计算这种状况 从失败切换到安装成功的状态 
                #这个 为True的很低 大多数为False 只有当系统中apt 出现问题时 才会复现这种问题
                if success == False and false_num == 0 and self.now_upgrade.upgrade_content != []:
                    logging.warning("Special Case switch success status from False to True...")
                    # success = True

                if success:
                    #当组列表为空时 表示现在的单独进行安装某些包或卸载，不发信号到控制面板
                    #升级完成后从升级列表删除
                    for groups in self.now_upgrade.upgrade_groups:
                        self.upgrade_data.upgrade_groups.remove(groups)

                    for pkg in self.now_upgrade.single_pkgs:
                        self.upgrade_data.single_pkgs.remove(pkg)

                    error_string = ''
                    error_desc = ''

                self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc)
                
                if success:
                    self.window_main.dbusController.CheckRebootRequired("self")
                    #安装完成之后 更新一次cache
                    logging.info("Install or Upgrade successful, so Now update Cache...")
                    self.window_main.refresh_cache()
        
        elif action == self.ACTION_INSTALL_SHUTDOWN:
            # self._release_install_lock()
            self._send_error_code(error_code)
            #插入数据库
            self.window_main.sqlite3_server.insert_info(self.ACTION_INSTALL,self.now_upgrade.single_pkgs,\
                                                        self.now_upgrade.upgrade_groups,[],success,error_string,error_desc)
            if success == True:
                #当升级完成时 将手动和自动安装的标志位全部清空
                self.window_main.install_mode.install_finished()
                
            self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc)

            #释放锁 允许关机
            if self.window_main.install_mode.inhibit_lock != None:
                self.window_main.install_mode.inhibit_lock.close()
                logging.info("Install Packages Finished and Releasing the shutdown lock...")
            else:
                logging.error("Install Packages Finished and Releasing the shutdown lock Failed...")
                #升级本身完成后 来释放关机锁
                self.window_main.dbusController.Quit(None)

        elif action == self.ACTION_CHECK_RESOLVER:
            if success == False:
                self.window_main.sqlite3_server.insert_info(self.action_mode,self.now_upgrade.single_pkgs,\
                                                            self.now_upgrade.upgrade_groups,[],success,error_string,error_desc)

                if self.action_mode != self.MODE_INSTALL_SYSTEM:
                    self.window_main.dbusController.UpdateDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc)
                else:
                    self.window_main.dbusController.DistupgradeDependResloveStatus(success,False,[''],[''],[''],error_string,error_desc)

        elif action == self.ACTION_DOWNLOADONLY:
            if self.now_upgrade.version_upgrade == True and self.now_upgrade.need_retry == True and success == False:
                #增加重试次数的限制
                if self.window_main.retry_limit != 0:
                    logging.warning("Retry the upgrade and installaton(%s) and retry number: %d",self.now_upgrade.upgrade_content,self.window_main.retry_limit)
                    self.window_main.start_install(self.action_mode,True,self.now_upgrade.upgrade_content)
                    self.window_main.retry_limit = self.window_main.retry_limit - 1
                    return

            if success == True and self.action_mode == self.MODE_INSTALL_PARTIAL:
                self.window_main.install_mode.tmp_content += self.now_upgrade.upgrade_content
            
            if success == False:
                self.window_main.sqlite3_server.insert_info(self.action_mode,self.now_upgrade.single_pkgs,\
                                                            self.now_upgrade.upgrade_groups,[],success,error_string,error_desc)
            
            #如果下载成功 就标志需要 安装重启
            if success == True:
                #安装成功的话再获取关机锁
                self.window_main.install_mode.get_inhibit_lock()

            self.window_main.install_mode.set_shutdown_install(success)

            self.window_main.dbusController.UpdateDownloadFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc)

        elif action == self.ACTION_UPDATE and self.action_mode == self.MODE_UPDATE_ALL:
            if success == False:
                # threading_emulate = threading.Thread(target=self.emulate_update)
                # threading_emulate.start()

                if ERROR_UPDATE_KEY_SIGNATURES in self.aptd_base.error_details:
                    error_desc = get_error_description_from_enum(ERROR_UPDATE_KEY_SIGNATURES)
                elif ERROR_UPDATE_NET_AUTHENTICATION in self.aptd_base.error_details:
                    error_desc = get_error_description_from_enum(ERROR_UPDATE_NET_AUTHENTICATION)
                elif ERROR_UPDATE_NOTREAD_SOURCES in self.aptd_base.error_details:
                    error_desc = get_error_description_from_enum(ERROR_UPDATE_NOTREAD_SOURCES)
                elif ERROR_UPDATE_INVALID_TIME in self.aptd_base.error_details:
                    error_desc = get_error_description_from_enum(ERROR_UPDATE_INVALID_TIME)
            
            if success:
                #开始生成列表
                self.window_main.start_available()
            else:
                self.window_main.dbusController.UpdateDetectFinished(success,[''],get_error_string_from_enum(ERROR_UPDATE_DEFAULT_FAILED),\
                                                                        error_string +' '+error_desc)
            self.window_main.sqlite3_server.insert_into_display("check_time",get_east_8_time()[0:-4])

        elif action == self.ACTION_UPDATE and self.action_mode == self.MODE_UPDATE_CACHE:
                self.window_main.dbusController.UpdateDetectFinished(success,[''],error_string,error_desc)
        elif action == self.ACTION_FIX_BROKEN:
            self.window_main.dbusController.FixBrokenStatusChanged(True,success,100,'',error_string,error_desc)
            logging.warning("fix broken packages is complete...")
            
            if success:
                logging.info("Fix broken packages is complete to success...")
                self.window_main.start_available()
            else:
                self.window_main.dbusController.UpdateDetectFinished(success,[''],\
                                            get_error_string_from_enum(ERROR_NOT_FIX_SYSTEM),error_string+' '+error_desc)
                logging.error("fix broken packages is complete to failed...")

        elif action == self.ACTION_FIX_INCOMPLETE:
            if success:
                logging.info("fix incomplete install success.")
            else:
                logging.warning("fix incomplete install failed.")

        elif action == self.ACTION_REMOVE_PACKAGES:
            self._release_install_lock()
            self.window_main.dbusController.PurgePackagesFinished(success,error_string,error_desc)
        
        elif action == self.ACTION_INSTALL_DEB:
            self._release_install_lock()
            #FIXME: '\r\n: \r\n\r\n'就认为是验证失败
            if success == False and '\r\n: \r\n\r\n' in self.aptd_base.error_details:
                error_string = _("Package validation failed and installation was rejected.")
                error_desc = ''
            self.window_main.dbusController.InstalldebFinished(success,error_string,error_desc)
            UpdateMsg = {}
            if success:
                status = 'success'
                UpdateMsg.update({"errorCode":" "})
            else:
                status = 'failed'
                UpdateMsg.update({"errorCode":str(error_string+" "+error_desc)})
            #apt发送数据
            if self.window_main.configs_uncover.getWithDefault("SystemStatus", "upload_installer_log", False) == True:
                
                UpdateMsg.update({"appname":str(self.window_main.deb_obj.get("debname","None").split("_")[0])})
                UpdateMsg.update({"source":str(self.window_main.deb_obj.get("source","kylin-system-updater"))})
                UpdateMsg.update({"status":str(status)})
                UpdateMsg.update({"new_version":str(self.window_main.deb_obj.get("debname","None").split("_")[1])})
                UpdateMsg.update({"old_version":str(self.window_main.deb_obj.get("old_version","None"))})
                self.window_main.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy())
                self.window_main.deb_obj = {}
        elif action == self.ACTION_BACKGROUND_UPGRADE:
            self._release_install_lock()
            UpdateMsg = {}
            if success:
                status = 'success'
            else:
                status = 'failed'
            self.window_main.collector.Generate_Msg(self.window_main.collector.background_list, self.action_mode)
            for bl in self.window_main.collector.background_list:
                pkg = self.window_main.collector.cache[bl]
                UpdateMsg.update({"appname":str(bl)})
                UpdateMsg.update({"source":"Kylin Background upgrade"})
                UpdateMsg.update({"status":str(status)})
                UpdateMsg.update({"errorCode":str(error_string+" "+error_desc)})
                if self.window_main.collector.background_version[bl]:
                    UpdateMsg.update({"old_version":self.window_main.collector.background_version[bl]})
                UpdateMsg.update({"new_version":self.window_main.collector.cache[bl].candidate.source_version})
                # self.window_main.collector.Upgrade_Process_Msg(self.action, UpdateMsg.copy())
            
            self.window_main.dbusController.UpdateInstallFinished(success,self.now_upgrade.upgrade_content,error_string,error_desc)


    def _start_install_lock(self, caller='Kylin System Updater'):
        self.window_main.configs_uncover.setValue("SystemStatus","abnormal_reboot",str(True))
        self.inhibit_shutdown.lock(caller=caller)

    def _release_install_lock(self):
        self.window_main.configs_uncover.setValue("SystemStatus","abnormal_reboot",str(False))
        self.inhibit_shutdown.unlock()

    def _message_to_plymouth(self,message):
        subprocess.call(["/bin/plymouth", "message", "--text", message])

    def _progress_to_plymouth(self,progress):
        tmp = ("--progress=%d"%progress)
        run_cmd = ["/bin/plymouth","system-update",tmp]
        subprocess.call(run_cmd)

    def _update_to_config(self,now_upgrade,pkgs_install,pkgs_upgrade,pkgs_remove):
        output_upgrade = {}

        output_upgrade.update({"upgrade_groups":now_upgrade.upgrade_groups})
        output_upgrade.update({"single_pkgs":now_upgrade.single_pkgs})
        output_upgrade.update({"pkgs_install":pkgs_install})
        output_upgrade.update({"pkgs_upgrade":pkgs_upgrade})
        output_upgrade.update({"pkgs_remove":pkgs_remove})


        #6 产生JSON文件
        with open(self.INSTALL_OUTPUT_JSON, 'w', encoding='utf-8') as f:
            json.dump(output_upgrade, f, ensure_ascii=False, indent=4)

        logging.info("Generate Jsonfile(%s) to complete... ",self.INSTALL_OUTPUT_JSON)
        logging.info("Update Packages list to config file in shutdown model...")

    def _config_to_upgrade(self):
        #读取组JSON文件
        with open(self.INSTALL_OUTPUT_JSON,'r') as f:
            upgrade_groups = []
            single_pkgs = []
            pkgs_install = []
            pkgs_upgrade = []
            pkgs_remove = []

            try:
                data = json.load(f)
                upgrade_groups = data["upgrade_groups"]
                single_pkgs = data["single_pkgs"]
                pkgs_install = data["pkgs_install"]
                pkgs_upgrade = data["pkgs_upgrade"]
                pkgs_remove = data["pkgs_remove"]
            except Exception as exc:
                logging.error(exc)
        
        return NowUpgradeMeta(self,upgrade_groups,single_pkgs),pkgs_install,pkgs_upgrade,pkgs_remove

    #将安装完成的插入数据库 安装失败的计算那些包安装失败了 分类插入数据库中
    #将安装失败的数据进行返回
    def _make_insert_info(self,success,is_cancelled,_now_upgrade,error_string,error_desc):
        false_num = 0
        #目前去掉打印 错误日志
        # error_desc = error_desc +'\n\n'+self.aptd_base.error_details
        #在安装失败 and 不是取消升级 则走下面的 否则不计算全部直接插入数据库
        if success == False and is_cancelled == False and self.action_mode != self.MODE_INSTALL_SYSTEM:
            #获取当前系统中最新的cache
            fresh_cache = Cache(rootdir=self.window_main.cache.rootdir)
            #获取调整包列表 去掉版本号
            adjust_pkgs = [i.split("=")[0] for i in self.upgrade_data.adjust_pkgs]

            #升级存在单包更新 失败后计算每一个包是否安装完成 相应判断进行插入
            for pkg in _now_upgrade.single_pkgs:
                pkg_obj = fresh_cache[pkg]
                
                #判断是否是源过滤调整的包 调整的话 判断安装版本 来解决是否安装成功
                if pkg in adjust_pkgs:
                    if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and  pkg_obj.name + '=' + pkg_obj.installed.source_version in self.upgrade_data.adjust_pkgs:
                        self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,True,'', '')
                    else:
                        false_num += 1
                        logging.warning("This single-package(%s) is not install or upgrade",pkg)
                        self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,False,error_string, error_desc)
                else:
                #非调整版本的计算方式
                    if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and pkg_obj.is_now_broken == False:
                        self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,True,'', '')
                    else:
                        false_num += 1
                        logging.warning("This single-package(%s) is not install or upgrade",pkg)
                        self.window_main.sqlite3_server.insert_info(self.action_mode,[pkg],[],self.upgrade_data.adjust_pkgs,False,error_string, error_desc)
            
            #组的计算是否升级成功的方式 将组按照单包来计算的
            if _now_upgrade.upgrade_groups != []:
                pkgs_install,pkgs_upgrade = self._make_pkgs_list(self.cache,self.upgrade_data.groups_pkgs,_now_upgrade.upgrade_groups,[])
                install_error_pkgs = []
                total_pkg = pkgs_install + pkgs_upgrade

                for pkg in total_pkg[::-1]:
                    pkg_obj = fresh_cache[pkg]
                    if pkg in adjust_pkgs:
                        if pkg_obj.is_installed == True and pkg_obj.is_now_broken == False and pkg_obj.installed.source_version + pkg_obj.name in self.upgrade_data.adjust_pkgs:
                            total_pkg.remove(pkg)
                        else:
                            install_error_pkgs.append(pkg)
                    else:
                        if pkg_obj._pkg.inst_state == apt_pkg.INSTSTATE_OK and pkg_obj._pkg.current_state == apt_pkg.CURSTATE_INSTALLED and pkg_obj.is_now_broken == False:
                            total_pkg.remove(pkg)
                        else:
                            install_error_pkgs.append(pkg)
                
                # group_error_log = '\n'+ "This groups-package"+str(install_error_pkgs)+" is not install or upgrade" + '\n'
                # logging.warning(group_error_log)
                #如果没有
                if total_pkg == []:
                    self.window_main.sqlite3_server.insert_info(self.action_mode,[],_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,True,'', '') 
                else:
                    false_num += 1
                    self.window_main.sqlite3_server.insert_info(self.action_mode,[],_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,False,error_string,error_desc)
            #关闭临时cache
            fresh_cache.close()
        #其他情况直接写入数据库 不进行计算
        else:
            #取消的话全部是失败
            if is_cancelled == True:
                false_num = len(_now_upgrade.single_pkgs) + len(_now_upgrade.upgrade_groups)
            self.window_main.sqlite3_server.insert_info(self.action_mode,_now_upgrade.single_pkgs,_now_upgrade.upgrade_groups,self.upgrade_data.adjust_pkgs,success,error_string, error_desc)
            
        return false_num

    def emulate_calcul_broken(self,pkgs):
        args = ["apt-get", "install","--simulate"]
        args = args + pkgs

        p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
        # logging.error(str(p.stdout))
        return p.stdout

    def emulate_update(self):
        args = ["apt-get", "update"]

        p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
        logging.warning(str(p.stdout))
        # return p.stdout

    def check_free_space(self,cache):
        err_sum = _("Not enough free disk space")
        err_msg = _("The upgrade needs a total of %s free space on "
                    "disk '%s'. "
                    "Please free at least an additional %s of disk "
                    "space on '%s'. %s")
        # specific ways to resolve lack of free space
        remedy_archivedir = _("Remove temporary packages of former "
                                "installations using 'sudo apt clean'.")
        remedy_boot = _("You can remove old kernels using "
                        "'sudo apt autoremove', and you could also "
                        "set COMPRESS=xz in "
                        "/etc/initramfs-tools/initramfs.conf to "
                        "reduce the size of your initramfs.")
        remedy_root = _("Empty your trash and remove temporary "
                        "packages of former installations using "
                        "'sudo apt clean'.")
        remedy_tmp = _("Reboot to clean up files in /tmp.")
        remedy_usr = _("")
        # check free space and error if its not enough
        try:
            cache.checkFreeSpace()
        except NotEnoughFreeSpaceError as e:
            # CheckFreeSpace examines where packages are cached
            archivedir = apt_pkg.config.find_dir("Dir::Cache::archives")
            err_long = ""
            for req in e.free_space_required_list:
                if err_long != "":
                    err_long += " "
                if req.dir == archivedir:
                    err_long += err_msg % (req.size_total, req.dir,
                                            req.size_needed, req.dir,
                                            remedy_archivedir)
                elif req.dir == "/boot":
                    err_long += err_msg % (req.size_total, req.dir,
                                            req.size_needed, req.dir,
                                            remedy_boot)
                elif req.dir == "/":
                    err_long += err_msg % (req.size_total, req.dir,
                                            req.size_needed, req.dir,
                                            remedy_root)
                elif req.dir == "/tmp":
                    err_long += err_msg % (req.size_total, req.dir,
                                            req.size_needed, req.dir,
                                            remedy_tmp)
                elif req.dir == "/usr":
                    err_long += err_msg % (req.size_total, req.dir,
                                            req.size_needed, req.dir,
                                            remedy_usr)
            # #当单包安装检查内存不够的时候，报错到控制面板 单包安装属于更新才使用的所以直接赋值为更新 再进行之后的报错处理
            if self.action_mode == self.MODE_INSTALL_SINGLE:
                self.action = self.ACTION_UPDATE
            raise UpdateBaseError(ERROR_NOT_DISK_SPACE,desc=err_sum)
        except SystemError:
            logging.exception("free space check failed")
        logging.info("Disk Check finished...")

# try aptdaemon
if os.path.exists("/usr/sbin/aptd") \
   and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ:
    # check if the gtkwidgets are installed as well
    try:
        from .InstallBackendAptdaemon import InstallBackendAptdaemon
    except ImportError:
        logging.exception("importing aptdaemon")

def get_backend(*args, **kwargs):
    """Select and return a package manager backend."""
    # try aptdaemon
    if (os.path.exists("/usr/sbin/aptd")
            and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ):
        # check if the gtkwidgets are installed as well
        try:
            return InstallBackendAptdaemon(*args, **kwargs)
        except NameError:
            logging.exception("using aptdaemon failed")

    # nothing found, raise
    raise Exception("No working backend found, please try installing "
                    "aptdaemon or synaptic")

class InhibitShutdownLock():
    # 禁止关机锁文件路径
    FILELOCK_PATH = "/tmp/lock/"
    SHUTDOWN_BLOCK_FILELOCK = "kylin-update.lock"
    
    def __init__(self):
        self.inhibit_lock = None
        self.pidfile = None

    #安装时禁止关机 进行加锁
    def lock(self, caller='Kylin System Updater'):
        """
        Send a dbus signal to logind to not suspend the system, it will be
        released when the return value drops out of scope
        """
        try:
            from gi.repository import Gio, GLib
            connection = Gio.bus_get_sync(Gio.BusType.SYSTEM)
            
            var, fdlist = connection.call_with_unix_fd_list_sync(
                'org.freedesktop.login1', '/org/freedesktop/login1',
                'org.freedesktop.login1.Manager', 'Inhibit',
                GLib.Variant('(ssss)',
                            ('shutdown',
                            caller, 'Installing Packages',
                            'block')),
                None, 0, -1, None, None)
            self.inhibit_lock = Gio.UnixInputStream(fd=fdlist.steal_fds()[var[0]])

            self.LockedPreventShutdown()
            logging.info("Shutdown Has been locked...")
        except Exception as e:
            logging.error(e)

    #解锁禁止关机 
    def unlock(self):
        try:
            self.unLockedEnableShutdown()
            if self.inhibit_lock != None:
                self.inhibit_lock.close()
                self.inhibit_lock == None
                logging.info("Shutdown Has been unlocked...")
            else:
                logging.info("Not locked and Quitting ...")
        except Exception as e:
            logging.error("unlock failed." + str(e))

    #安装时禁止关机 进行加锁
    def LockedPreventShutdown(self):

        #不为空是表示以及被锁
        if self.pidfile != None:
            logging.error("self.pidfile file disc not is None,Has been locked...")
            return False

        if not os.path.exists(self.FILELOCK_PATH):
            #不存在创建
            logging.info("File(%s) is not exists and will be create",self.FILELOCK_PATH)
            os.makedirs(self.FILELOCK_PATH)
        else:
            #当目录存在时进行删除 不删除进行创建文件的话会报错 
            # file cannot be locked.[Errno 11] Resource temporarily unavailable
            # 资源被占用报错
            shutil.rmtree(self.FILELOCK_PATH)
            logging.info("File(%s) is exists and will be delete and create",self.FILELOCK_PATH)
            os.makedirs(self.FILELOCK_PATH)        

        try:
            self.pidfile = open(os.path.join(self.FILELOCK_PATH, self.SHUTDOWN_BLOCK_FILELOCK), "w+")
            fcntl.flock(self.pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
            return True
        except Exception as e:
            logging.error("file cannot be locked." + str(e))
            self.pidfile.close()
            self.pidfile = None
            return False

    #解锁禁止关机 
    def unLockedEnableShutdown(self):
        #未加锁退出
        if not self.pidfile:
            logging.info("Not locked and Quitting ...")
            return False
        try:
            fcntl.flock(self.pidfile, fcntl.LOCK_UN)
            self.pidfile.close()
            self.pidfile = None

            # Fix 修复权限问题 当普通用户无法使用 所以直接删除目录
            if os.path.exists(self.FILELOCK_PATH):
                shutil.rmtree(self.FILELOCK_PATH)
                logging.info('Emptying the lockPath(%s) is complete...',self.FILELOCK_PATH)
            else:
                logging.info("Emptying the lockPath(%s) is Failed...",self.FILELOCK_PATH)

            return True
        except Exception as e:
            logging.error("unlock failed." + str(e))
            self.pidfile.close()
            self.pidfile = None
            return False   

class UpdateSafeManager():
    KYSEC_STATUS = "/sys/kernel/security/kysec/status"
    KYSEC_EXECTL = "/sys/kernel/security/kysec/exectl"

    KYSEC_EXECUT_CONTROL = 0
    KYSEC_NETWORK_CONTROL = 1
    KYSEC_SHUTDOWN_CODE = 0

    def __init__(self):
        self.bus = dbus.SystemBus()
        self.safe_status = False
        self.safe_exectl_code = self.KYSEC_SHUTDOWN_CODE
        self.check_status()

    def check_status(self):
        self._check_safe_status()
        self._check_safe_exectl()

    def _check_safe_status(self):
        if os.path.exists(self.KYSEC_STATUS):
            with open(self.KYSEC_STATUS, 'r') as f:
                data = f.read()
                if data != "0":
                    self.safe_status = True
    
    def _check_safe_exectl(self):
        if self.safe_status == True:
            if os.path.exists(self.KYSEC_EXECTL):
                with open(self.KYSEC_EXECTL, 'r') as f:
                    data = f.read()
                    self.safe_exectl_code = int(data)
                    logging.info("Now kylin Sec has opened and exectl status:%s...",data)

    def reset_safe(self):
        if self.safe_status == True:
            self._set_kysec_status(self.KYSEC_EXECUT_CONTROL,self.safe_exectl_code)
            self._set_kysec_status(self.KYSEC_NETWORK_CONTROL,2)

    def shutdown_safe(self):
        if self.safe_status == True:
            self._set_kysec_status(self.KYSEC_EXECUT_CONTROL,self.KYSEC_SHUTDOWN_CODE)
            self._set_kysec_status(self.KYSEC_NETWORK_CONTROL,self.KYSEC_SHUTDOWN_CODE)

    def _set_kysec_status(self,fun,value):
        try:
            obj = self.bus.get_object('com.kylin.kysec', '/xattr')
            interface = dbus.Interface(obj,dbus_interface='com.kylin.kysec.xattr')
            retval = interface.kysec_xattr_set_func_status(fun,value,timeout=0.5)
            logging.info("Set kysec_xattr_set_func_status %s...",str(value))
            return True
        except Exception as e:
            logging.error("Set kylin Sec Failed and fun:%d value:%d Error msg:" + str(e),fun,value)
            return False
